package com.shbatitstwo.core;


import org.dom4j.Document;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;

import com.shbatitstwo.common.Const;
import com.shbatitstwo.datasource.pooled.PooledDataSource;
import com.shbatitstwo.datasource.unpooled.UnPooledDataSource;
import com.shbatitstwo.transaction.Transaction;
import com.shbatitstwo.transaction.jdbc.JdbcTransaction;
import com.shbatitstwo.transaction.managed.ManagedTransaction;


import javax.sql.DataSource;
import java.io.InputStream;
import java.util.HashMap;
import java.util.Map;


/**
 * @Auther: sh
 * @Version 1.0
 * @Description: 连接工厂构建器， 通过build方法解析shbatis-config.xml文件，构建SqlSessionFactory对象
 */
public class SqlSessionFactoryBuilder {

    public SqlSessionFactoryBuilder() {
    }

    /**
     * 解析shbatis-config.xml文件，构建SqlSessionFactory对象
     *
     * @param inputStream 指向shbatis-config.xml文件的输入流
     * @return SqlSessionFactory对象
     */
    public SqlSessionFactory build(InputStream inputStream) {
        SqlSessionFactory sqlSessionFactory = null;
        try {
            SAXReader saxReader = new SAXReader();
            Document document = saxReader.read(inputStream);
            Element environments = (Element) document.selectSingleNode("/environments/configuration");
            String defaultId = environments.attributeValue("default");
            Element environment = (Element) document.selectSingleNode("/configuration/environments/environment[@id='" + defaultId + "']");
            Element transactionManagerElt = environment.element("transactionManager");
            Element dataSourceElt = environment.element("dataSource");

            // 数据源
            DataSource dataSource = getDataSource(dataSourceElt);
            // 获取事务管理器
            Transaction transaction = getTransactionManager(transactionManagerElt, dataSource);
            // 获取映射语句
            Map<String, ShMappedStatement> mappedStatementMap = null;

            sqlSessionFactory = new SqlSessionFactory(transaction, mappedStatementMap);
        } catch (
                Exception e) {
            throw new RuntimeException(e);
        }


        return sqlSessionFactory;
    }


    private DataSource getDataSource(Element dataSourceElt) {
        DataSource dataSource = null;
        Map<String, String> dataSourceMap = new HashMap<>();
        String type = dataSourceElt.attributeValue("type").trim().toUpperCase();
        for (Element element : dataSourceElt.elements()) {
            dataSourceMap.put(element.attributeValue("name"), element.attributeValue("value"));
        }
        if (Const.UN_POOLED_DATASOURCE.equals(type)) {
            String driver = dataSourceMap.get("driver");
            String url = dataSourceMap.get("url");
            String username = dataSourceMap.get("username");
            String password = dataSourceMap.get("password");
            dataSource = new UnPooledDataSource(driver, url, username, password);
        }
        if (Const.POOLED_DATASOURCE.equals(type)) {
            dataSource = new PooledDataSource();
        }
        return dataSource;
    }

    private Transaction getTransactionManager(Element transactionManagerElt, DataSource dataSource) {
        Transaction transaction = null;
        String type = transactionManagerElt.attributeValue("type").trim().toUpperCase();
        if (Const.JDBC_TRANSACTION.equals(type)) {
            // 默认开启事务
            transaction = new JdbcTransaction(dataSource, true);
        }
        if (Const.MANAGER_TRANSACTION.equals(type)) {
            // 默认开启事务
            transaction = new ManagedTransaction();
        }
        return transaction;
    }
}

